#define _GNU_SOURCE
#include "daemon_sub_process.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/reboot.h>
#include <signal.h>
#include "log/log.h"

SubProcess *daemon_sub_process_init(char *cmd_param)
{

    SubProcess *sp = (SubProcess *)malloc(sizeof(SubProcess));
    sp->pid = 0; // 进程还没有产生
    sp->cmd_param = cmd_param;
    sp->fail_count = 0;

    return sp;
}

int daemon_sub_process_checkStart(SubProcess *sp)
{
    // 检查子进程是否正在运行中, 如果正在运行，直接返回
    int status = 0;
    // WNOHANG: 不会等待子进程结束，会很快返回，如果进程正在运行，返回0,
    // 如果进程已结束，将其结束时的状态值， 保存到status中
    if (sp->pid > 0 && (waitpid(sp->pid, &status, WNOHANG) == 0))
    {
        log_debug("进程(%s)正在运行中", sp->cmd_param);
        return 0;
    }
    // 如果子进程是异常结束，统计失败次数, 如果超过了最大失败次数，则重启系统
    if (status != 0)
    {
        sp->fail_count++;
        if (sp->fail_count > MAX_FAIL_COUNT)
        {
            reboot(RB_AUTOBOOT);
        }
    }

    // 则创建子进程，并在子进程中运行对应的程序
    sp->pid = fork();
    if (sp->pid == 0)
    {
        // 运行指定程序模块
        /*
        gateway_test app  子进程
        gateway_test ota  子进程
        */
        char *argv[] = {EXE_PATH, sp->cmd_param, NULL};
        execve(EXE_PATH, argv, NULL);
        log_error("----, %s", sp->cmd_param);
        // 找不到对应的程序模块，结束当前进程
        _exit(EXIT_FAILURE);
    }

    return 0;
}

void daemon_sub_process_stop(SubProcess *sp)
{
    // kill子进程, 并发送SIGTERM信号通知子进程
    kill(sp->pid, SIGTERM);
    // 等待子进程结束
    waitpid(sp->pid, NULL, 0);
    // 释放内存
    free(sp);
}
